package com.zzz.poker.netty.handler;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket 业务处理
 */
@Component
@ChannelHandler.Sharable
public class WebSocketHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
    private static final Logger logger = LoggerFactory.getLogger(WebSocketHandler.class);

    // 存储所有连接的 channel
    private static final ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>();

    /**
     * 处理 WebSocket 帧
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {
        // 处理关闭帧
        if (frame instanceof CloseWebSocketFrame) {
            handleCloseFrame(ctx, (CloseWebSocketFrame) frame);
            return;
        }

        // 处理 ping 帧
        if (frame instanceof PingWebSocketFrame) {
            ctx.writeAndFlush(new PongWebSocketFrame(frame.content().retain()));
            return;
        }

        // 只处理文本帧，忽略二进制帧
        if (!(frame instanceof TextWebSocketFrame)) {
            throw new UnsupportedOperationException("Unsupported frame type: " + frame.getClass().getName());
        }

        // 处理文本帧
        String request = ((TextWebSocketFrame) frame).text();
        logger.info("Received message: {}", request);

        // 业务处理示例
        String response = "Server response: " + request;
        logger.info("channelId:{}", ctx.channel().id().asLongText());
        ctx.writeAndFlush(new TextWebSocketFrame(response));

    }

    /**
     * 处理关闭帧
     */
    private void handleCloseFrame(ChannelHandlerContext ctx, CloseWebSocketFrame frame) {
        logger.info("Received close frame");
        ctx.close();
    }

    /**
     * 客户端连接时触发
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        String channelId = channel.id().asLongText();
        channelMap.put(channelId, channel);
        logger.info("Client connected: {}", channelId);
    }

    /**
     * 客户端断开连接时触发
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        String channelId = channel.id().asLongText();
        channelMap.remove(channelId);
        logger.info("Client disconnected: {}", channelId);
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("WebSocket error: ", cause);
        ctx.close();
    }

    /**
     * 用户事件触发，用于处理心跳检测
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            //有一段时间没有收到任何数据 关闭连接
            if (event.state() == IdleState.READER_IDLE) {
                logger.info("Reader idle, closing connection");
                ctx.close();
            }
            //有一段时间没有发送任何数据
            if (event.state() == IdleState.WRITER_IDLE) {
                logger.info("Writer idle, sending ping");
                ctx.writeAndFlush(new PingWebSocketFrame());
            }
        }
    }

    /**
     * 广播消息给所有连接的客户端
     */
    public void broadcast(String message) {
        TextWebSocketFrame frame = new TextWebSocketFrame(message);
        channelMap.forEach((id, channel) -> {
            if (channel.isActive()) {
                channel.writeAndFlush(frame);
            } else {
                channelMap.remove(id);
            }
        });
    }
}